#include <stdio.h>
#include <stdlib.h>
#include <linux/mxcfb.h>
#include <linux/videodev.h>
#include <sys/mman.h>
#include <dirent.h>
#include <mntent.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <linux/i2c-dev.h>
#include <dlfcn.h>

#include "oslite.h"
#include "clilib.h"

//#include "utils.h"

#include "imxdriver.h"

#define MAX_STREAM 2


static pthread_t sig_thread_id;
static sigset_t mask;
static int m_hspi=0;




int cli_regio(parse_t * pars_p, char *result){
    int fd; 
	int ret;
	unsigned int reg=0,val=-1;
	REGVAL_t regval ={0};
	fd = open(DEVICE_NAME,O_RDWR);
	if(fd <=0){
		print("can't open fd %d \n\r",fd);
		return 0;
	}

	cget_integer(pars_p,reg,(int*)&reg);
	cget_integer(pars_p,val,(int*)&val);
	regval.addr = reg;
	regval.val = val;
	
	if(val ==-1){
		ret =ioctl(fd, DRIVER_READ_REG32,&regval);	
		printf("reg(0x%8x) val(0x%8x) \n\r",regval.addr,regval.val);
	}
	else{
		ret =ioctl(fd, DRIVER_WRITE_REG32,&regval);	
		printf("reg(0x%8x) val(0x%8x) \n\r",regval.addr,regval.val);
	}	
	
	close(fd);
	return 0;
}



int cli_gpiodir(parse_t * pars_p, char *result){
	int gpio=0,val=0,dir=0;
	int fd;
	int ret=0;
	GPIOVAL_t gpioval={0};
	
	
	cget_integer(pars_p,gpio,&gpio);
	cget_integer(pars_p,0,&dir);		
	cget_integer(pars_p,0,&val);

	
	fd = open(DEVICE_NAME,O_RDWR);
	if(fd <=0){
		print("can't open fd %d \n\r",fd);
		return 0;
	}
	
	gpioval.gpio = gpio;
	gpioval.val  = val;
	gpioval.dir  = dir&1; 

	ret =ioctl(fd, DRIVER_gpio_dir, &gpioval);	
	printf("gpio(%d) dir(%d) val(0x%x)\n\r",gpioval.gpio,gpioval.dir,gpioval.val);

	close(fd);
	
	return 0;
}



int cli_gpio_list(parse_t * pars_p, char *result){
	int start=0,count=32;
	int i;
	int fd;
	int ret=0;
	GPIOVAL_t gpioval={0};
	
	
	cget_integer(pars_p,start,&start);
	cget_integer(pars_p,count,&count);
	
	fd = open(DEVICE_NAME,O_RDWR);
	if(fd <=0){
		print("can't open fd %d \n\r",fd);
		return 0;
	}
	for(i=0;i<count;i++){
		gpioval.gpio = start +i;
		gpioval.val  = 0;
		ret =ioctl(fd, DRIVER_gpio_get_value, &gpioval);	
		printf("0x%x= gpio_read(%d)\n\r",gpioval.val,gpioval.gpio);
	}
	
	close(fd);
	
	return 0;
}





int cli_spi(parse_t * pars_p, char *result){
	
	int fd;
	SPIIO_t spi={0};
	int ret=0;
	int i;
	//static char m_txbuff[256]={0};	
	
	cget_string(pars_p,spi.buff,spi.buff,sizeof(spi.buff));
	fd = open(DEVICE_NAME,O_RDWR);
	if(fd <=0){
		print("can't open fd %d \n\r",fd);
		return 0;
	}
	if(strlen(spi.buff)>0){
		spi.length = strlen(spi.buff);
		ret = ioctl(fd,DRIVER_SPI_WRITE,&spi);			
		printf("spi write ret %d,",ret);
	}
	else{
		spi.length = sizeof(spi.buff);
		ret = ioctl(fd,DRIVER_SPI_READ,&spi);	
		printf("spi read len(%d)\n\r[",spi.length);
		for(i=0;i<spi.length;i++){
			printf("%x,",spi.buff[i]);
		}	
		printf("]\n\r",spi.buff[i]);
		}

	close(fd);	
}


int cli_spiclk(parse_t * pars_p, char *result){
	int enable=0;
	int fd;
	int ret=0;

	
	cget_integer(pars_p,enable,&enable);	
	fd = open(DEVICE_NAME,O_RDWR);
	if(fd <=0){
		print("can't open fd %d \n\r",fd);
		return 0;
	}
	ret = ioctl(fd,DRIVER_SPI_CLOCK,&enable);	
	close(fd);
	return 0;
}	

#include "vpu_test.h"

static OS_Task_t amethyst_task=0;
int Amethyst_Test_Init(int debug);
int Amethyst_Test_Term(void);
void AmethPearlTask(void *pvParameters);
unsigned char  AmethifHandleMessage( unsigned char* pMsg);
int ReadSPIMessage(void *iobuff,int msglength);
int WriteSPIMessage(void *iobuff,int msglength);
void gpio_write_to_spi(int on);
unsigned char m_ametbuff[120];

struct v4l2_buffer v4l2_buf={0};
static unsigned int m_userdata=0;
static int m_v4lon=0;

int GetCameraSlice(unsigned char *buffer,int offset, int length){
	if(m_userdata){
		if(offset + length <= v4l2_buf.length){
			memcpy((void*)buffer,(void*)(m_userdata+ offset),length);
		}	
	}	
	return length;
}


//ret = v4l_start_capturing();
//



int cli_amettask(parse_t * pars_p, char *result){
int ret=0;
int debug_slice=1;
	cget_integer(pars_p,debug_slice,&debug_slice);	

	if(amethyst_task==0){
		v4l_capture_setup(640,480, 30);
		if(debug_slice==0){
			ret = v4l_start_capturing();
			if(ret ==0){
				v4l_get_capture_data(&v4l2_buf,&m_userdata);
				v4l_put_capture_data(&v4l2_buf);
				m_v4lon =1;
			}	
		}
		printf("start Amet Task \n\r");
		gpio_write_to_spi(0);
		OS_MSleep(100);
		gpio_write_to_spi(1);
		if(m_hspi==0)
			m_hspi = open(DEVICE_NAME,O_RDWR);
		Amethyst_Test_Init(debug_slice);
		amethyst_task = OS_TaskCreate(0x1000,"amethyst", AmethPearlTask,0,(void *)0);		
	}
	else{
		//v4l_stop_capturing();
		if(amethyst_task){
			printf("Stop Amet Task \n\r");
			if(m_v4lon)
				v4l_stop_capturing();
			m_v4lon=0;
			Amethyst_Test_Term();
			OS_TaskDelete(amethyst_task);
			amethyst_task =0;
			if(m_hspi)
				close(m_hspi);
			m_hspi =0;
		}	
	}
	return 0;
}	


int  cli_ametread(parse_t * pars_p, char *result){
	int ret =0;
	int len=0;
	if(m_hspi==0)
		m_hspi = open(DEVICE_NAME,O_RDWR);
	
	ret  = ReadSPIMessage(m_ametbuff,sizeof(m_ametbuff));	
	if(ret >0){
		len = AmethifHandleMessage(&m_ametbuff[2]);
	}
	printf("read(%d) handle(%d) \n\r",ret,len);
	return 0;
}

int cli_ametwrite(parse_t * pars_p, char *result){
	int ret =0;
	if(m_hspi==0)
		m_hspi = open(DEVICE_NAME,O_RDWR);
	
	ret  = WriteSPIMessage(m_ametbuff,118);	
	printf("write(%d)\n\r",ret);
	return 0;
}	

int cli_ametgpio(parse_t * pars_p, char *result){
	int gpio=0;
	cget_integer(pars_p,gpio,&gpio);	
	if(m_hspi==0)
		m_hspi = open(DEVICE_NAME,O_RDWR);
	
	gpio_write_to_spi(gpio);
	printf("gpio(%d) \n\r",gpio);
	return 0;
}	

int cli_ametgbg(parse_t * pars_p, char *result){
		int fd;
		SPIIO_t spi={0};
		int ret=0;
		int length=120;
		int i;
		//static char m_txbuff[256]={0};	
		cget_integer(pars_p,length,&length);			
		fd = open(DEVICE_NAME,O_RDWR);
		if(fd <=0){
			print("can't open fd %d \n\r",fd);
			return 0;
		}
		if(length >0){
			spi.length = length;
			for(i=0;i<length;i++){
				spi.buff[i]=i+1;
			}
			ret = ioctl(fd,DRIVER_SPI_WRITE,&spi);	
			printf("spi write len(%d)\n\r[",spi.length);
		}
		else{
			spi.length = sizeof(spi.buff);
			ret = ioctl(fd,DRIVER_SPI_READ,&spi);	
			printf("spi read len(%d)\n\r[",spi.length);
			for(i=0;i<spi.length;i++){
				printf("%x,",spi.buff[i]);
			}	
			printf("]\n\r");
		}
	
		close(fd);	
	
}		

void RegisterDebug(void){
	register_command ("spi",cli_spi,"<mode><wbits><speed><data><len><slave><loop>");
	register_command ("spiclk",cli_spiclk,"<on/off>");
	register_command ("amettask",cli_amettask,"<debug=1,0=camera slice> togel(on/off)");
	register_command ("ametread",cli_ametread,"read data");
	register_command ("ametwrite",cli_ametwrite,"write data");
	register_command ("ametgpio",cli_ametgpio,"1=on 0=off");
	register_command ("ametgbg",cli_ametgbg,"<len>");
}


int m_finish=0;



void gpio_write_to_spi(int on){
GPIOVAL_t gpioval={0};	
int ret=0;
	if(m_hspi==0){
		fprintf(stderr,"m_hspi is NULL\n\r");
		return 0;
	}
	gpioval.gpio = 111;
	gpioval.val  = on & 1;
	gpioval.dir  = 1; 
	ret =ioctl(m_hspi, DRIVER_gpio_dir, &gpioval);
	return 0;
}


int ReadSPIMessage(void *iobuff,int msglength){
	SPIIO_t spi={0};
	int ret=0;
	int iolen=0;
	int length=0;
	unsigned int Timeout;
	unsigned int StartTime;
	unsigned char *pbuf = (unsigned char *)iobuff;
	if(m_hspi==0){
		fprintf(stderr,"m_hspi is NULL\n\r");
		return 0;
	}
	
	StartTime = OS_GetKHClock();
	while(msglength>0){
		length = msglength;
		if(length >sizeof(spi.buff))
			length = sizeof(spi.buff);
		spi.length = length;					
		ret = ioctl(m_hspi,DRIVER_SPI_READ,&spi);	
		if(ret <0){
			fprintf(stderr,"SPI Timeout\n\r");			
			return -1;
		}
		memcpy(pbuf,spi.buff,length);
		iolen += spi.length;
		pbuf  += spi.length;
		msglength -= spi.length;
		if(OS_GetKHClock() - StartTime  > 100){
			fprintf(stderr,"rx SPI Timeout\n\r");			
			break;
		}	
	}
	return iolen;
	//return spi.length;
}


int WriteSPIMessage(void *iobuff,int msglength){
	SPIIO_t spi={0};
	REGVAL_t regval ={0};
	
	int iolen=0;
	int length=0;
	unsigned int status=0;
	int ret=0;
	unsigned char *pbuf = (unsigned char *)iobuff;
	if(m_hspi==0){
		fprintf(stderr,"m_hspi is NULL\n\r");
		return 0;
	}
	
	spi.length = 128;
	memset(spi.buff,0,8);
	spi.buff[8]=0xd7;
	spi.buff[9]=0x0;
	memcpy(&spi.buff[10],pbuf,msglength);
	ret = ioctl(m_hspi,DRIVER_SPI_WRITE,&spi);		
	
	gpio_write_to_spi(1);
	if(m_hspi){
		int i;
		for(i=0;i<10;i++){
			ret = ioctl(m_hspi,DRIVER_SPI_STATUS,&status);
			if((status & BIT(0))){
				break;
			}
			OS_MSleep(100);
		}
		if(i==10){
			printf("TX Status TimeOut\n\r");
		}
	}
	//OS_MSleep(20);
	gpio_write_to_spi(0);
	//OS_MSleep(100);
	return spi.length;
}








int main(int argc, char *argv[])
{
    int ret;
	OS_Task_t hTask=0;
//	snd_ctl_card_info_t *p_info = NULL;
    printf("main %s\n",__DATE__);
	

	



//	system("insmod /mxdriver.ko");		

	
	
	TesttoolInit();
    RegisterDebug();
    TesttoolRun();
	
    return 0;
}

